<?php
/**
 * 接口请求频率限制
 *
 * @copyright 139.com Inc
 */

class ApiRequestLimit
{
    //单用户请求接口每小时上限
    const REQUEST_LIMIT_LEVEL_0 = 150;	//普通授权
    const REQUEST_LIMIT_LEVEL_1 = 450;	//高级授权
    const REQUEST_LIMIT_LEVEL_2 = '';	//合作伙伴授权

    //单用户发布说客每小时上限
    const POSTTEXT_LIMIT_LEVEL_0 = 30;
    const POSTTEXT_LIMIT_LEVEL_1 = 90;
    const POSTTEXT_LIMIT_LEVEL_2 = 120;

    //单用户发布评论每小时上限
    const COMMENT_LIMIT_LEVEL_0 = 60;
    const COMMENT_LIMIT_LEVEL_1 = 180;
    const COMMENT_LIMIT_LEVEL_2 = 240;

    //单用户关注每小时上限
    const FOLLOW_LIMIT_LEVEL_0 = 60;
    const FOLLOW_LIMIT_LEVEL_1 = 180;
    const FOLLOW_LIMIT_LEVEL_2 = 240;

    //单用户关注每天上限
    const FOLLOW_DAY_LIMIT_LEVEL_0 = 200;
    const FOLLOW_DAY_LIMIT_LEVEL_1 = 600;
    const FOLLOW_DAY_LIMIT_LEVEL_2 = 800;

    //memcached key
    const MCKEY_API_REQUEST 	= 'apireq';
    const MCKEY_API_POSTTEXT 	= 'apipost';
    const MCKEY_API_COMMENT 	= 'apicom';
    const MCKEY_API_FOLLOW 		= 'apifw';
    const MCKEY_API_FOLLOW_DAY 	= 'apifwday';



    /**
     * 检查单IP请求接口每小时上限
     * @param  $app_id
     * @param  $app_level
     * @throws Exception
     */
    public static function CheckRequestByIp ($app_id, $app_level)
    {
        $request_limit = self::REQUEST_LIMIT_LEVEL_0;

        switch ($app_level) {
            case 0:
                $request_limit = self::REQUEST_LIMIT_LEVEL_0;
                break;
            case 1:
                $request_limit = self::REQUEST_LIMIT_LEVEL_1;
                break;
            case 2:
                $request_limit = self::REQUEST_LIMIT_LEVEL_2;
                return true;
                break;
        }
        $ip = ApiUtility::GetRemoteIp();
        $key = self::MCKEY_API_REQUEST . $app_id . '_' . $ip;
        $val = MemcacheProxy::getCache($key);
        if ($val) {
            if ($val > $request_limit) {
            	ApiLog::ReqlimitLog($app_id, $app_level, $key, $val, $request_limit);
                throw new Exception(ApiErr::API_EC_API_OVER_REQUESTLIMIT);
            }
        }
        MemcacheProxy::incCache($key, 3600);
    }

    /**
     * 检查单用户请求接口每小时上限
     * @param  $app_id
     * @param  $app_uid
     * @param  $app_level
     * @throws Exception
     */
    public static function CheckRequestByUid ($app_id, $user_id, $app_level)
    {
        $request_limit = self::REQUEST_LIMIT_LEVEL_0;

        switch ($app_level) {
            case 0:
                $request_limit = self::REQUEST_LIMIT_LEVEL_0;
                break;
            case 1:
                $request_limit = self::REQUEST_LIMIT_LEVEL_1;
                break;
            case 2:
                $request_limit = self::REQUEST_LIMIT_LEVEL_2;
                return true;
                break;
        }
        $key = self::MCKEY_API_REQUEST . $app_id . '_' . $user_id;
        $val = MemcacheProxy::getCache($key);
        if ($val) {
            if ($val > $request_limit) {
            	ApiLog::ReqlimitLog($app_id, $app_level, $key, $val, $request_limit);
                throw new Exception(ApiErr::API_EC_API_OVER_REQUESTLIMIT);
            }
        }
        MemcacheProxy::incCache($key, 3600);
    }

    /**
     * 检查单用户发布说客每小时上限
     */
    public static function CheckPostText ()
    {
    	$app_id = $GLOBALS['current_app_id'];
    	$user_id = $GLOBALS['current_user_id'];
    	$app_level = $GLOBALS['current_app_level'];

        $posttext_limit = self::POSTTEXT_LIMIT_LEVEL_0;

        switch ($app_level) {
            case 0:
                $posttext_limit = self::POSTTEXT_LIMIT_LEVEL_0;
                break;
            case 1:
                $posttext_limit = self::POSTTEXT_LIMIT_LEVEL_1;
                break;
            case 2:
                $posttext_limit = self::POSTTEXT_LIMIT_LEVEL_2;
                break;
        }
        $key = self::MCKEY_API_POSTTEXT . $app_id . '_' . $user_id;
        $val = MemcacheProxy::getCache($key);
        if ($val) {
            if ($val > $posttext_limit) {
            	ApiLog::ReqlimitLog($app_id, $app_level, $key, $val, $posttext_limit);
                throw new Exception(ApiErr::API_EC_TIMELINE_OVER_POSTTEXTLIMIT);
            }
        }
        MemcacheProxy::incCache($key, 3600);
    }

    /**
     * 检查单用户发布评论每小时上限
     */
    public static function CheckComment ()
    {
    	$app_id = $GLOBALS['current_app_id'];
    	$user_id = $GLOBALS['current_user_id'];
    	$app_level = $GLOBALS['current_app_level'];

        $comment_limit = self::COMMENT_LIMIT_LEVEL_0;

        switch ($app_level) {
            case 0:
                $comment_limit = self::COMMENT_LIMIT_LEVEL_0;
                break;
            case 1:
                $comment_limit = self::COMMENT_LIMIT_LEVEL_1;
                break;
            case 2:
                $comment_limit = self::COMMENT_LIMIT_LEVEL_2;
                break;
        }
        $key = self::MCKEY_API_COMMENT . $app_id . '_' . $user_id;
        $val = MemcacheProxy::getCache($key);
        if ($val) {
            if ($val > $comment_limit) {
            	ApiLog::ReqlimitLog($app_id, $app_level, $key, $val, $comment_limit);
                throw new Exception(ApiErr::API_EC_TIMELINE_OVER_COMMENTLIMIT);
            }
        }
        MemcacheProxy::incCache($key, 3600);
    }

    /**
     * 检查单用户关注频率上线
     */
    public static function CheckFollow ()
    {
    	$app_id = $GLOBALS['current_app_id'];
    	$user_id = $GLOBALS['current_user_id'];
    	$app_level = $GLOBALS['current_app_level'];

        $follow_limit = self::FOLLOW_LIMIT_LEVEL_0;
        $follow_day_limit = self::FOLLOW_DAY_LIMIT_LEVEL_0;

        switch ($app_level) {
            case 0:
                $follow_limit = self::FOLLOW_LIMIT_LEVEL_0;
                $follow_day_limit = self::FOLLOW_DAY_LIMIT_LEVEL_0;
                break;
            case 1:
                $follow_limit = self::FOLLOW_LIMIT_LEVEL_1;
                $follow_day_limit = self::FOLLOW_DAY_LIMIT_LEVEL_1;
                break;
            case 2:
                $follow_limit = self::FOLLOW_LIMIT_LEVEL_2;
                $follow_day_limit = self::FOLLOW_DAY_LIMIT_LEVEL_2;
                break;
        }
        //one hour
        $key = self::MCKEY_API_FOLLOW . $app_id . '_' . $user_id;
        $val = MemcacheProxy::getCache($key);
        if ($val) {
            if ($val > $follow_limit) {
            	ApiLog::ReqlimitLog($app_id, $app_level, $key, $val, $follow_limit);
                throw new Exception(ApiErr::API_EC_REL_OVER_FOLLOWHOURLIMIT);
            }
        }
        MemcacheProxy::incCache($key, 3600);

        //one day
        $key = self::MCKEY_API_FOLLOW_DAY . $app_id . '_' . $user_id;
        $val = MemcacheProxy::getCache($key);
        if ($val) {
            if ($val > $follow_day_limit) {
            	ApiLog::ReqlimitLog($app_id, $app_level, $key, $val, $follow_day_limit);
                throw new Exception(ApiErr::API_EC_REL_OVER_FOLLOWDAYLIMIT);
            }
        }
        MemcacheProxy::incCache($key, 3600*24);
    }

}
